package com.zsxb.crm.utils;

import com.zsxb.crm.constant.LoginConstant;
import com.zsxb.crm.enumeration.ResultCodeEnum;
import com.zsxb.crm.exception.BaseException;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * JWT工具类
 */
@Slf4j
public class JwtUtils {
    // Token的过期时间，设置为24小时（24 * 60分钟 * 60秒 * 1000毫秒）
    private static final Long tokenExpireTime = 24*60*60*1000L;
    private static SecretKey tokenSignKey = Keys.hmacShaKeyFor("M0PKKI6pYGVWWfDZw90a0lTpGYX1d4AQ".getBytes());
    /**
     * 生成用户Token
     * @param userId 用户ID
     * @param username 用户名
     * @return 生成的Token字符串
     */
    public static String createToken(Long userId, String username,String loginIp){
        // 构建Token信息，设置主题、过期时间、用户ID和用户名，并使用密钥进行签名，最后返回紧凑格式的Token字符串
        String token = Jwts.builder()
                .setSubject(LoginConstant.USER_INFO)
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime))
                .claim(LoginConstant.USER_ID, userId)
                .claim(LoginConstant.USERNAME, username)
                .claim(LoginConstant.LOGIN_IP,loginIp)
                .signWith(SignatureAlgorithm.HS256,tokenSignKey)
                .compact();
        return token;
    }

    /**
     * 解析JWT令牌并返回其中的声明
     *
     * @param token 待解析的JWT令牌字符串
     * @return JWT令牌中的声明
     * @throws BaseException 当令牌为空、过期或无效时抛出此异常
     */
    public static Claims parseToken(String token){
        // 检查令牌是否为空，为空则抛出异常，表示登录认证失败
        if (token==null){
            throw new BaseException(ResultCodeEnum.ADMIN_LOGIN_AUTH);
        }
        try{
            // 使用签名密钥初始化JWT解析器
            JwtParser jwtParser = Jwts.parser();
            jwtParser.setSigningKey(tokenSignKey);
            // 解析JWT令牌并返回其中的声明
            return jwtParser.parseClaimsJws(token).getBody();
        }catch (ExpiredJwtException e){
            // 当捕获到令牌过期异常时，抛出异常表示令牌已过期
            throw new BaseException(ResultCodeEnum.TOKEN_EXPIRED);
        }catch (JwtException e){
            // 当捕获到其他JWT异常时，抛出异常表示令牌无效
            throw new BaseException(ResultCodeEnum.TOKEN_INVALID);
        }
    }

}

